Client config reporting (3.x) — stage 1 (groundwork): SESSION_ID + DRIVER_CONFIG plumbing - #973
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds configurable driver configuration reporting to Sequence Diagram(s)sequenceDiagram
participant ClusterBuilder
participant Configuration
participant ConnectionFactory
participant ControlConnection
participant DefaultDriverConfigReporter
ClusterBuilder->>Configuration: enable reporting
ConnectionFactory->>DefaultDriverConfigReporter: create reporter
ControlConnection->>ConnectionFactory: open(host, true)
ConnectionFactory->>DefaultDriverConfigReporter: addOption(options, true)
DefaultDriverConfigReporter-->>ConnectionFactory: SESSION_ID and DRIVER_CONFIG
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Comment |
9366dd6 to
1ec3ff3
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@driver-core/src/main/java/com/datastax/driver/core/Connection.java`:
- Around line 1301-1310: The DriverConfigReporter currently lives on the
cluster-wide Connection.Factory, causing multiple Session instances to share one
SESSION_ID. Move reporter creation and ownership from Factory to the actual
Session layer, and ensure each session’s connections reuse that session-scoped
reporter; update affected wiring and tests to preserve per-session grouping.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: a97e0b8c-9fad-48bf-9c86-bd7c8c548623
📒 Files selected for processing (8)
driver-core/src/main/java/com/datastax/driver/core/Cluster.javadriver-core/src/main/java/com/datastax/driver/core/Configuration.javadriver-core/src/main/java/com/datastax/driver/core/Connection.javadriver-core/src/main/java/com/datastax/driver/core/ControlConnection.javadriver-core/src/main/java/com/datastax/driver/core/DefaultDriverConfigReporter.javadriver-core/src/main/java/com/datastax/driver/core/DriverConfigReporter.javadriver-core/src/test/java/com/datastax/driver/core/DefaultDriverConfigReporterTest.javadriver-core/src/test/java/com/datastax/driver/core/DriverConfigReportingCcmIT.java
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
driver-core/src/test/java/com/datastax/driver/core/DriverConfigReportingCcmTest.java (1)
195-205: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy liftAggregate
system.clientsacross all nodes.
client_optionsis node-local, butallDriverRows()queries only the node selected bysession(). On a multi-node cluster this can omit the control row or pooled rows, making the “exactly one DRIVER_CONFIG” and disabled-reporting assertions incomplete or flaky. Query every node, or explicitly pin and aggregate the control-connection node; include node identity in connection keys if aggregating.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@driver-core/src/test/java/com/datastax/driver/core/DriverConfigReportingCcmTest.java` around lines 195 - 205, Update allDriverRows() to query and aggregate system.clients from every cluster node instead of only the session-selected node, preserving the DRIVER_NAME filter and including node identity in any connection keys used by the assertions. Ensure the resulting rows cover control and pooled connections so the existing count and disabled-reporting checks remain complete.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In
`@driver-core/src/test/java/com/datastax/driver/core/DriverConfigReportingCcmTest.java`:
- Around line 195-205: Update allDriverRows() to query and aggregate
system.clients from every cluster node instead of only the session-selected
node, preserving the DRIVER_NAME filter and including node identity in any
connection keys used by the assertions. Ensure the resulting rows cover control
and pooled connections so the existing count and disabled-reporting checks
remain complete.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 3cd52ce3-2107-4f14-989d-e96c708f2887
📒 Files selected for processing (8)
driver-core/pom.xmldriver-core/src/main/java/com/datastax/driver/core/Cluster.javadriver-core/src/main/java/com/datastax/driver/core/Connection.javadriver-core/src/main/java/com/datastax/driver/core/DefaultDriverConfigReporter.javadriver-core/src/main/java/com/datastax/driver/core/DriverConfigReporter.javadriver-core/src/main/java/com/datastax/driver/core/NoopDriverConfigReporter.javadriver-core/src/test/java/com/datastax/driver/core/DriverConfigReportingCcmTest.javadriver-core/src/test/java/com/datastax/driver/core/NoopDriverConfigReporterTest.java
🚧 Files skipped from review as they are similar to previous changes (1)
- driver-core/src/main/java/com/datastax/driver/core/Cluster.java
6cfd5f3 to
0073d32
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@driver-core/pom.xml`:
- Around line 171-179: Prevent Connection.Factory from triggering a Jackson
NoClassDefFoundError during connection setup when reporting dependencies are
absent. Update DefaultDriverConfigReporter and the reporting initialization
around Connection.Factory so Jackson-dependent classes are loaded only after
availability is verified, or make jackson-core and jackson-databind required
instead of optional; preserve addOption()’s handling for unavailable reporting.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 7ebf3485-784f-4f81-9a28-103e79c40ea1
📒 Files selected for processing (11)
driver-core/pom.xmldriver-core/src/main/java/com/datastax/driver/core/Cluster.javadriver-core/src/main/java/com/datastax/driver/core/Configuration.javadriver-core/src/main/java/com/datastax/driver/core/Connection.javadriver-core/src/main/java/com/datastax/driver/core/ControlConnection.javadriver-core/src/main/java/com/datastax/driver/core/DefaultDriverConfigReporter.javadriver-core/src/main/java/com/datastax/driver/core/DriverConfigReporter.javadriver-core/src/main/java/com/datastax/driver/core/NoopDriverConfigReporter.javadriver-core/src/test/java/com/datastax/driver/core/DefaultDriverConfigReporterTest.javadriver-core/src/test/java/com/datastax/driver/core/DriverConfigReportingCcmTest.javadriver-core/src/test/java/com/datastax/driver/core/NoopDriverConfigReporterTest.java
0073d32 to
9d61c1b
Compare
9d61c1b to
a48ac94
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@driver-core/pom.xml`:
- Line 167: Add <optional>true</optional> to the jackson-core and
jackson-databind dependency declarations in driver-core/pom.xml, leaving their
existing versions and configuration unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 8cbf6aa0-0778-4ac5-8373-9d8624f5a532
📒 Files selected for processing (12)
driver-core/pom.xmldriver-core/src/main/java/com/datastax/driver/core/Cluster.javadriver-core/src/main/java/com/datastax/driver/core/Configuration.javadriver-core/src/main/java/com/datastax/driver/core/Connection.javadriver-core/src/main/java/com/datastax/driver/core/ControlConnection.javadriver-core/src/main/java/com/datastax/driver/core/DefaultDriverConfigReporter.javadriver-core/src/main/java/com/datastax/driver/core/DriverConfigReporter.javadriver-core/src/main/java/com/datastax/driver/core/NoopDriverConfigReporter.javadriver-core/src/test/java/com/datastax/driver/core/DefaultDriverConfigReporterTest.javadriver-core/src/test/java/com/datastax/driver/core/DriverConfigReportingCcmTest.javadriver-core/src/test/java/com/datastax/driver/core/NoopDriverConfigReporterTest.javapom.xml
💤 Files with no reviewable changes (1)
- pom.xml
…stage 1) Stage 1 (groundwork) of driver configuration reporting for the 3.x driver -- the 3.x counterpart of the 4.x feature (DRIVER-381/scylladb#967). Lets the driver report its effective configuration to ScyllaDB at connection time via new STARTUP options, so operators can inspect driver settings (system.clients.client_options) while investigating incidents. Two STARTUP options are added: - SESSION_ID: a dedicated, driver-generated UUID sent on every connection (control and pool) unconditionally, like DRIVER_NAME and DRIVER_VERSION, so the server can group all of a Cluster's connections -- including across multiple Sessions obtained from the same Cluster, since the control connection has no affiliation with any single Session. Independent of the user-settable CLIENT_ID. - DRIVER_CONFIG: a compact JSON blob describing the effective configuration, sent only on the control connection. Stage 1 emits only {"version":1}; the full report follows in stage 2 (scylladb#974). Enabled by default; opt out with Cluster.builder().withDriverConfigReporting(false). The report is built once, while the Cluster initializes, and the resulting string is reused for every control connection that Cluster opens -- it is never rebuilt while the session is in flight. Building it is fail-safe: any failure is swallowed and simply leaves DRIVER_CONFIG unset instead of breaking cluster initialization. New DriverConfigReporter / DefaultDriverConfigReporter (package com.datastax.driver.core) build the blob. Connection.Factory, of which there is one per Cluster, holds that Cluster's session id and the built report, and hands the report to the control connection as a constructor argument -- null everywhere else, which is what suppresses reporting. The control connection is identified by threading a reportConfig flag from ControlConnection.tryConnect through a new Connection.Factory.open(host, reportConfig) overload, since 3.x has no pre-existing signal identifying the control connection at STARTUP time. jackson-core/jackson-databind are enforced as plain required dependencies (as they already were in released 3.11.5.17), used to build the JSON blob; the orphaned jackson-dataformat-yaml dependency (dead since the Scylla Cloud config code was removed) is dropped, so consumers no longer inherit SnakeYAML. system.clients.client_options is per node, so DRIVER_CONFIG only appears on the node holding the control connection. Fixes DRIVER-382 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
a48ac94 to
40b507f
Compare
…rs them driver-core has no Failsafe plugin binding (only bound in driver-tests/osgi/*), and Surefire's default includes never match *IT.java, so these CCM integration tests were silently never executed by `mvn verify -Pshort`/`-Plong`. Renaming to *Test.java matches Surefire's default discovery pattern, mirroring the fix already applied to DriverConfigReportingCcmIT in #973. Renamed: TabletsIT, ZeroTokenNodesIT, LWTLoadBalancingIT, SchemaBuilderIT. Now that LWTLoadBalancingTest actually runs, it surfaced a real (previously undetected) bug: both test methods constructed a SimpleStatement with bound values and then passed it to session.prepare(), which rejects statements carrying values. Fixed by preparing the value-free statement and binding values only on the resulting PreparedStatement, as the tests already intended. All classes verified live against ScyllaDB 2026.1.0: Tablets (3), ZeroTokenNodes (7), and LWTLoadBalancing (2) tests pass. SchemaBuilderTest's 6 methods remain pre-existing enabled=false, unrelated to this fix. Fixes #981. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
What ☑️
Stage 1 (groundwork) of client configuration reporting for the 3.x driver — the 3.x counterpart of the 4.x feature. It lets the driver report its effective client configuration to ScyllaDB at connection time, so operators can inspect driver settings (via
system.clients.client_options) while investigating incidents. Follows the cross-driver JSON schema design.This is phase 1 of 2 — it lands the plumbing; the full configuration report (all groups) comes in phase 2 (#974).
Behavior 👶
Two
STARTUPoptions are added:SESSION_ID— a dedicated, driver-generated UUID, sent on every connection (control and pool), unconditionally — like theDRIVER_NAME/DRIVER_VERSIONoptions the driver already always sends. One id perCluster, shared by every connection opened from it — including across multipleSessions obtained from the sameCluster— so the server can group them. It's Cluster-scoped rather than Session-scoped because the control connection isn't tied to any particularSession(see discussion in review). Independent of the user-settableCLIENT_ID.DRIVER_CONFIG— a compact JSON blob, sent only on the control connection. Enabled by default; opt out withCluster.builder().withDriverConfigReporting(false). Stage 1 emits only{"version":1}; the full report follows in phase 2.system.clients.client_optionsis per node, so only the node holding the control connection stores this — consumers must query and aggregate across all nodes to see the full picture.The report is built once, while the
Clusterinitializes, and the resulting string is reused for every control connection thatClusteropens — it is never rebuilt while the session is in flight, so a control-connection reconnect costs nothing and always reports the same configuration. Building it is fail-safe: any failure is swallowed and simply leavesDRIVER_CONFIGunset rather than breaking cluster initialization.Changes ✍️
DriverConfigReporter/DefaultDriverConfigReporter(packagecom.datastax.driver.core) build theDRIVER_CONFIGpayload — a singlebuildReport()call that returns the JSON, ornullif it couldn't be built.Connection.Factory(one perCluster) holds that cluster'sSESSION_IDand, when reporting is enabled, the report built at initialization time. It hands the report to the control connection as a constructor argument —nulleverywhere else, andnullis exactly what suppressesDRIVER_CONFIG. No reporter instance is retained, and none is constructed at all when reporting is off.Connection.onOptionsReady(), right after the existingapplicationInfostartup-option hook.reportConfigflag fromControlConnection.tryConnectthrough a newConnection.Factory.open(host, reportConfig)overload — 3.x has no pre-existing signal that identifies the control connection atSTARTUPtime.Cluster.Builder→Configuration.Builder→Configuration(default true).jackson-core/jackson-databindare enforced as plain required dependencies (as they already were in released 3.11.5.17), used byDefaultDriverConfigReporterto build the JSON blob; the orphanedjackson-dataformat-yamldependency (dead since the Scylla Cloud config code was removed) is dropped, so consumers no longer inherit SnakeYAML. OSGi manifests carry mandatorycom.fasterxml.jackson.*;version="[2.18,3)"imports accordingly.Testing 🔨
Unit tests
DefaultDriverConfigReporterTest: reporting is enabled by default (bothConfiguration.builder()andCluster.builder()), the stage-1 report is{"version":1}, and report building is fail-safe (a throwing build yieldsnullinstead of propagating).driver-corecompiles and unit tests are green.Integration tests
DriverConfigReportingCcmTest(live ScyllaDB,@ScyllaVersion≥ 2026.1; named*Testrather than*ITso Surefire's default discovery actually picks it up — see review discussion) asserts what the server stores insystem.clients:SESSION_IDis stored for every connection of the cluster, andDRIVER_CONFIGfor exactly one (the control connection);Sessions opened from the sameClustershare oneSESSION_ID;SESSION_IDis still stored butDRIVER_CONFIGis not.The cluster under test uses the default configuration (no
withDriverConfigReportingcall), so these also cover default-on end-to-end. Each cluster's connections are identified by theSESSION_IDthe driver generated for it, so the assertions can't be confused by another cluster's rows. The end-to-end verification of the full report lands with phase 2.Verified live against ScyllaDB 2026.1 — all 3 methods pass.
Manual tests 🖐
Captured the actual
STARTUPframes on the wire with tshark, against a live single-node ScyllaDB 2026.1.0 (CCM), to directly confirm the plumbing — same method as #967's stage-1 verification for the 4.x driver.Environment: single node ScyllaDB 2026.1.0 on CCM, contact point
127.0.0.1:9042, minimalCluster.builder().addContactPoint("127.0.0.1").withPort(9042)— samples 1 and 2 with nowithDriverConfigReportingcall at all (i.e. the default), sample 3 withwithDriverConfigReporting(false).Sample 1: Control connection STARTUP frame (default configuration)
Note
Note both
DRIVER_CONFIGandSESSION_IDare present, with no configuration needed to enable themSample 2: Pool connection STARTUP frame (default configuration)
Note
Note only
SESSION_IDis present — same value as Sample 1, since it's the same clusterSample 3: Control connection STARTUP frame (
withDriverConfigReporting(false))Note
Note
DRIVER_CONFIGis gone, whileSESSION_IDis still sent — it is not governed by the flagNote on cross-driver consistency⚠️
The merged 4.x stage 1 (#967) currently differs from what this PR now does, on three points requested in review here: it ships disabled by default (
advanced.driver-config-reporting.enabled = false), it gatesSESSION_IDbehind that same flag, and it rebuilds the blob on every control-connection init. Happy to align 4.x in a follow-up if we want the two drivers to behave identically — just say the word and I'll open it.Follow-up (phase 2)
Fixes DRIVER-382
🤖 Generated with Claude Code